<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SQL更新语句比较动画演示</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色和字体 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3b82f6',
                        secondary: '#6b7280',
                        success: '#10b981',
                        warning: '#f59e0b',
                        danger: '#ef4444',
                        accent: '#8b5cf6',
                        dark: '#1f2937',
                        light: '#f9fafb'
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <!-- 自定义工具类 -->
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .card-gradient {
                background: linear-gradient(135deg, #ffffff 0%, #f3f4f6 100%);
            }
            .table-shadow {
                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
            }
            .transition-medium {
                transition: all 0.3s ease;
            }
            .scale-in {
                animation: scaleIn 0.3s ease-out;
            }
            .highlight {
                animation: highlight 1s ease;
            }
            .pulse {
                animation: pulse 1.5s infinite;
            }
            .fade-in {
                animation: fadeIn 0.5s ease-in;
            }
            .step-indicator {
                transition: all 0.3s ease;
            }
            .step-indicator.active {
                background-color: theme('colors.accent');
                color: white;
                transform: scale(1.05);
            }
            @keyframes scaleIn {
                0% { transform: scale(0.95); opacity: 0; }
                100% { transform: scale(1); opacity: 1; }
            }
            @keyframes highlight {
                0% { background-color: rgba(139, 92, 246, 0.3); }
                100% { background-color: transparent; }
            }
            @keyframes pulse {
                0%, 100% { opacity: 1; }
                50% { opacity: 0.6; }
            }
            @keyframes fadeIn {
                0% { opacity: 0; }
                100% { opacity: 1; }
            }
            .line-through {
                text-decoration: line-through;
            }
            .sql-highlight {
                @apply bg-blue-100 text-blue-800 px-1 rounded font-semibold;
            }
            .join-line {
                position: absolute;
                background-color: #8b5cf6;
                height: 2px;
                transform-origin: left;
                z-index: 10;
                opacity: 0.8;
            }
            .subquery-box {
                border: 2px dashed #8b5cf6;
                position: relative;
            }
            .subquery-arrow {
                position: absolute;
                width: 0;
                height: 0;
                border-left: 10px solid transparent;
                border-right: 10px solid transparent;
                border-bottom: 10px solid #8b5cf6;
                opacity: 0;
                transition: opacity 0.3s ease;
            }
        }
    </style>
</head>
<body class="bg-gray-50 font-inter text-dark min-h-screen">
    <!-- 页面头部 -->
    <header class="bg-white shadow-md">
        <div class="container mx-auto px-4 py-6">
            <h1 class="text-3xl font-bold text-center">
                <i class="fa fa-database text-accent mr-2"></i>
                SQL更新语句比较动画演示
            </h1>
            <p class="text-center text-secondary mt-2">直观理解子查询与JOIN两种更新方式的执行过程</p>
        </div>
    </header>

    <!-- 主内容区域 -->
    <main class="container mx-auto px-4 py-8">
        <!-- SQL语句对比 -->
        <div class="mb-8">
            <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
                <!-- 子查询更新 -->
                <div class="card-gradient rounded-xl p-6 table-shadow">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-primary flex items-center justify-center text-white mr-3">
                            <i class="fa fa-sitemap"></i>
                        </div>
                        <h2 class="text-xl font-bold">子查询更新方式</h2>
                    </div>
                    <div class="bg-gray-900 text-gray-100 p-4 rounded-lg font-mono text-sm overflow-x-auto">
                        <pre id="sqlSubquery">update SC set grade=90 
where sno ='21021103' 
and cno in 
(select cno from course where cname='C语言');</pre>
                    </div>
                    <div class="mt-4 p-3 bg-primary/10 rounded-lg">
                        <p class="text-sm text-gray-700">
                            <strong>执行流程：</strong>先执行子查询获取C语言课程的课程号，再更新SC表中对应学生的成绩
                        </p>
                    </div>
                </div>
                
                <!-- JOIN更新 -->
                <div class="card-gradient rounded-xl p-6 table-shadow">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-accent flex items-center justify-center text-white mr-3">
                            <i class="fa fa-link"></i>
                        </div>
                        <h2 class="text-xl font-bold">JOIN更新方式</h2>
                    </div>
                    <div class="bg-gray-900 text-gray-100 p-4 rounded-lg font-mono text-sm overflow-x-auto">
                        <pre id="sqlJoin">update SC join course on SC.cno=course.cno 
set grade = 90 
where sno='21021103' and cname='C语言';</pre>
                    </div>
                    <div class="mt-4 p-3 bg-accent/10 rounded-lg">
                        <p class="text-sm text-gray-700">
                            <strong>执行流程：</strong>先将SC表与course表通过课程号连接，再更新满足条件的记录
                        </p>
                    </div>
                </div>
            </div>
        </div>

        <!-- 操作控制 -->
        <div class="mb-8 bg-white rounded-xl p-6 table-shadow">
            <h3 class="text-xl font-bold text-dark mb-4">执行流程演示</h3>
            
            <!-- 步骤选择 -->
            <div class="flex flex-wrap gap-4 mb-6">
                <button id="btnSubquery" class="px-6 py-2 bg-primary text-white rounded-lg transition-medium flex items-center">
                    <i class="fa fa-play-circle mr-2"></i>演示子查询更新
                </button>
                <button id="btnJoin" class="px-6 py-2 bg-accent text-white rounded-lg transition-medium flex items-center">
                    <i class="fa fa-play-circle mr-2"></i>演示JOIN更新
                </button>
                <button id="btnReset" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg transition-medium flex items-center ml-auto">
                    <i class="fa fa-refresh mr-2"></i>重置演示
                </button>
            </div>
            
            <!-- 步骤指示器 -->
            <div class="flex justify-between items-center mb-6">
                <div id="step1" class="step-indicator active px-4 py-2 rounded-lg text-sm font-medium">
                    <i class="fa fa-database mr-1"></i> 原始数据
                </div>
                <div class="text-secondary">
                    <i class="fa fa-long-arrow-right"></i>
                </div>
                <div id="step2" class="step-indicator px-4 py-2 rounded-lg text-sm font-medium bg-gray-200">
                    <i class="fa fa-search mr-1"></i> 查询条件
                </div>
                <div class="text-secondary">
                    <i class="fa fa-long-arrow-right"></i>
                </div>
                <div id="step3" class="step-indicator px-4 py-2 rounded-lg text-sm font-medium bg-gray-200">
                    <i class="fa fa-link mr-1"></i> 数据关联
                </div>
                <div class="text-secondary">
                    <i class="fa fa-long-arrow-right"></i>
                </div>
                <div id="step4" class="step-indicator px-4 py-2 rounded-lg text-sm font-medium bg-gray-200">
                    <i class="fa fa-wrench mr-1"></i> 更新操作
                </div>
                <div class="text-secondary">
                    <i class="fa fa-long-arrow-right"></i>
                </div>
                <div id="step5" class="step-indicator px-4 py-2 rounded-lg text-sm font-medium bg-gray-200">
                    <i class="fa fa-check-circle mr-1"></i> 结果展示
                </div>
            </div>
            
            <!-- 执行说明 -->
            <div id="executionInfo" class="p-4 bg-gray-100 rounded-lg">
                <p class="text-gray-700">
                    <i class="fa fa-info-circle text-primary mr-2"></i>
                    <span id="infoText">请选择一个演示方式开始观看SQL更新语句的执行过程</span>
                </p>
            </div>
        </div>
        
        <!-- 数据表格 -->
        <div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
            <!-- 学生表 -->
            <div class="card-gradient rounded-xl p-6 table-shadow">
                <h3 class="text-xl font-bold text-dark mb-4 flex items-center">
                    <i class="fa fa-users text-primary mr-2"></i>
                    学生表 (Student)
                </h3>
                
                <div class="overflow-x-auto">
                    <table id="studentTable" class="min-w-full bg-white rounded-lg overflow-hidden">
                        <thead class="bg-primary text-white">
                            <tr>
                                <th class="px-3 py-2 text-left text-sm">学号 (sno)</th>
                                <th class="px-3 py-2 text-left text-sm">姓名 (sname)</th>
                                <th class="px-3 py-2 text-left text-sm">专业 (major)</th>
                            </tr>
                        </thead>
                        <tbody id="studentTableBody">
                            <!-- 数据将通过JavaScript动态生成 -->
                        </tbody>
                    </table>
                </div>
            </div>
            
            <!-- 课程表 -->
            <div class="card-gradient rounded-xl p-6 table-shadow">
                <h3 class="text-xl font-bold text-dark mb-4 flex items-center">
                    <i class="fa fa-book text-accent mr-2"></i>
                    课程表 (Course)
                </h3>
                
                <div class="overflow-x-auto">
                    <table id="courseTable" class="min-w-full bg-white rounded-lg overflow-hidden">
                        <thead class="bg-accent text-white">
                            <tr>
                                <th class="px-3 py-2 text-left text-sm">课程号 (cno)</th>
                                <th class="px-3 py-2 text-left text-sm">课程名 (cname)</th>
                                <th class="px-3 py-2 text-left text-sm">学分 (credit)</th>
                            </tr>
                        </thead>
                        <tbody id="courseTableBody">
                            <!-- 数据将通过JavaScript动态生成 -->
                        </tbody>
                    </table>
                </div>
            </div>
            
            <!-- 成绩表 -->
            <div class="card-gradient rounded-xl p-6 table-shadow">
                <h3 class="text-xl font-bold text-dark mb-4 flex items-center">
                    <i class="fa fa-graduation-cap text-warning mr-2"></i>
                    成绩表 (SC)
                </h3>
                
                <div class="overflow-x-auto">
                    <table id="scTable" class="min-w-full bg-white rounded-lg overflow-hidden">
                        <thead class="bg-warning text-white">
                            <tr>
                                <th class="px-3 py-2 text-left text-sm">学号 (sno)</th>
                                <th class="px-3 py-2 text-left text-sm">课程号 (cno)</th>
                                <th class="px-3 py-2 text-left text-sm">成绩 (grade)</th>
                            </tr>
                        </thead>
                        <tbody id="scTableBody">
                            <!-- 数据将通过JavaScript动态生成 -->
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
        
        <!-- 比较分析 -->
        <div class="card-gradient rounded-xl p-6 table-shadow">
            <h3 class="text-xl font-bold text-dark mb-4 flex items-center">
                <i class="fa fa-balance-scale text-primary mr-2"></i>
                两种更新方式的比较
            </h3>
            
            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                <div class="bg-white p-4 rounded-lg shadow-sm">
                    <h4 class="font-semibold text-dark mb-3 flex items-center">
                        <i class="fa fa-check-circle text-success mr-2"></i>
                        子查询方式的特点
                    </h4>
                    <ul class="list-disc list-inside text-gray-700 space-y-2">
                        <li>逻辑清晰，容易理解</li>
                        <li>适合简单的嵌套查询场景</li>
                        <li>子查询先执行，结果作为主查询的条件</li>
                        <li>可能在大数据量时性能较差</li>
                    </ul>
                </div>
                
                <div class="bg-white p-4 rounded-lg shadow-sm">
                    <h4 class="font-semibold text-dark mb-3 flex items-center">
                        <i class="fa fa-check-circle text-success mr-2"></i>
                        JOIN方式的特点
                    </h4>
                    <ul class="list-disc list-inside text-gray-700 space-y-2">
                        <li>连接条件更直观</li>
                        <li>通常在复杂查询中性能更好</li>
                        <li>一次操作关联多个表</li>
                        <li>便于查看和管理连接关系</li>
                    </ul>
                </div>
            </div>
            
            <div class="mt-6 p-4 bg-gray-100 rounded-lg">
                <h4 class="font-semibold text-dark mb-2">性能考虑</h4>
                <p class="text-gray-700 mb-2">
                    对于简单的更新操作，两种方式性能差异不大。但在复杂查询或大数据量情况下，JOIN方式通常更高效，因为：
                </p>
                <ul class="list-disc list-inside text-gray-700 space-y-1">
                    <li>数据库优化器可以更好地优化JOIN操作</li>
                    <li>JOIN通常避免了多次表扫描</li>
                    <li>JOIN可以利用索引提高查询效率</li>
                </ul>
            </div>
        </div>
    </main>

    <!-- 页脚 -->
    <footer class="bg-white py-6 mt-12 border-t border-gray-200">
        <div class="container mx-auto px-4 text-center text-secondary">
            <p>SQL更新语句比较动画演示 © 2024</p>
        </div>
    </footer>

    <!-- 连接线条和动画容器 -->
    <div id="animationContainer" class="fixed top-0 left-0 w-full h-full pointer-events-none z-20">
        <!-- 动画元素将通过JavaScript动态添加 -->
    </div>

    <!-- JavaScript -->
    <script>
        // 定义数据库表数据
        const students = [
            { sno: '21021101', sname: '张三', major: '计算机科学' },
            { sno: '21021102', sname: '李四', major: '软件工程' },
            { sno: '21021103', sname: '王五', major: '数据科学' },
            { sno: '21021104', sname: '赵六', major: '人工智能' }
        ];

        const courses = [
            { cno: 'CS001', cname: 'C语言', credit: 4 },
            { cno: 'CS002', cname: '数据结构', credit: 3 },
            { cno: 'CS003', cname: '操作系统', credit: 4 },
            { cno: 'CS004', cname: '数据库原理', credit: 3 }
        ];

        // 原始成绩数据（用于重置）
        const originalScores = [
            { sno: '21021101', cno: 'CS001', grade: 85 },
            { sno: '21021101', cno: 'CS002', grade: 78 },
            { sno: '21021102', cno: 'CS001', grade: 92 },
            { sno: '21021102', cno: 'CS003', grade: 88 },
            { sno: '21021103', cno: 'CS001', grade: 75 },  // 这个记录将被更新
            { sno: '21021103', cno: 'CS004', grade: 90 },
            { sno: '21021104', cno: 'CS002', grade: 83 },
            { sno: '21021104', cno: 'CS003', grade: 79 }
        ];

        // 当前使用的成绩数据
        let scores = JSON.parse(JSON.stringify(originalScores));

        // DOM元素
        const studentTableBody = document.getElementById('studentTableBody');
        const courseTableBody = document.getElementById('courseTableBody');
        const scTableBody = document.getElementById('scTableBody');
        const infoText = document.getElementById('infoText');
        const animationContainer = document.getElementById('animationContainer');
        
        // 按钮元素
        const btnSubquery = document.getElementById('btnSubquery');
        const btnJoin = document.getElementById('btnJoin');
        const btnReset = document.getElementById('btnReset');
        
        // 步骤指示器
        const step1 = document.getElementById('step1');
        const step2 = document.getElementById('step2');
        const step3 = document.getElementById('step3');
        const step4 = document.getElementById('step4');
        const step5 = document.getElementById('step5');

        // 动画延迟常量
        const ANIMATION_DELAY = 1500;

        // 初始化页面
        function initializePage() {
            renderTables();
            resetSteps();
            updateInfoText('请选择一个演示方式开始观看SQL更新语句的执行过程');
        }

        // 渲染所有表格
        function renderTables() {
            renderStudentTable();
            renderCourseTable();
            renderSCTable();
        }

        // 渲染学生表
        function renderStudentTable() {
            studentTableBody.innerHTML = '';
            
            students.forEach(student => {
                const row = document.createElement('tr');
                row.className = 'border-b transition-medium hover:bg-gray-50';
                
                // 高亮要更新的学生
                const highlightClass = student.sno === '21021103' ? 'bg-blue-50 font-medium' : '';
                
                row.innerHTML = `
                    <td class="px-3 py-2 ${highlightClass}">${student.sno}</td>
                    <td class="px-3 py-2 ${highlightClass}">${student.sname}</td>
                    <td class="px-3 py-2 ${highlightClass}">${student.major}</td>
                `;
                
                studentTableBody.appendChild(row);
            });
        }

        // 渲染课程表
        function renderCourseTable() {
            courseTableBody.innerHTML = '';
            
            courses.forEach(course => {
                const row = document.createElement('tr');
                row.className = 'border-b transition-medium hover:bg-gray-50';
                
                // 高亮C语言课程
                const highlightClass = course.cname === 'C语言' ? 'bg-purple-50 font-medium' : '';
                
                row.innerHTML = `
                    <td class="px-3 py-2 ${highlightClass}">${course.cno}</td>
                    <td class="px-3 py-2 ${highlightClass}">${course.cname}</td>
                    <td class="px-3 py-2 ${highlightClass}">${course.credit}</td>
                `;
                
                courseTableBody.appendChild(row);
            });
        }

        // 渲染成绩表
        function renderSCTable() {
            scTableBody.innerHTML = '';
            
            scores.forEach(score => {
                const row = document.createElement('tr');
                row.className = 'border-b transition-medium hover:bg-gray-50';
                
                // 高亮要更新的记录
                const isTargetRecord = score.sno === '21021103' && score.cno === 'CS001';
                const highlightClass = isTargetRecord ? 'bg-yellow-50 font-medium' : '';
                
                row.innerHTML = `
                    <td class="px-3 py-2 ${highlightClass}">${score.sno}</td>
                    <td class="px-3 py-2 ${highlightClass}">${score.cno}</td>
                    <td class="px-3 py-2 ${highlightClass}">${score.grade}</td>
                `;
                
                scTableBody.appendChild(row);
            });
        }

        // 重置步骤指示器
        function resetSteps() {
            // 重置所有步骤样式
            [step1, step2, step3, step4, step5].forEach(step => {
                step.classList.remove('active');
                step.classList.add('bg-gray-200');
            });
            
            // 激活第一步
            step1.classList.add('active');
            step1.classList.remove('bg-gray-200');
            
            // 清除所有动画元素
            animationContainer.innerHTML = '';
        }

        // 更新信息文本
        function updateInfoText(text) {
            infoText.innerHTML = text;
        }

        // 高亮步骤
        function highlightStep(stepNumber) {
            // 重置所有步骤
            [step1, step2, step3, step4, step5].forEach(step => {
                step.classList.remove('active');
                step.classList.add('bg-gray-200');
            });
            
            // 高亮当前步骤
            const steps = [step1, step2, step3, step4, step5];
            if (stepNumber >= 0 && stepNumber < steps.length) {
                steps[stepNumber].classList.add('active');
                steps[stepNumber].classList.remove('bg-gray-200');
            }
        }

        // 高亮表中的特定行
        function highlightTableRow(tableBody, rowIndex, duration = 1000) {
            const rows = tableBody.querySelectorAll('tr');
            if (rowIndex >= 0 && rowIndex < rows.length) {
                const row = rows[rowIndex];
                row.classList.add('highlight');
                
                setTimeout(() => {
                    row.classList.remove('highlight');
                }, duration);
            }
        }

        // 创建连接线
        function createConnectionLine(startElement, endElement, duration = 1000) {
            const startRect = startElement.getBoundingClientRect();
            const endRect = endElement.getBoundingClientRect();
            
            const startX = startRect.left + startRect.width / 2;
            const startY = startRect.top + startRect.height / 2;
            const endX = endRect.left + endRect.width / 2;
            const endY = endRect.top + endRect.height / 2;
            
            // 计算线条长度和角度
            const length = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
            const angle = Math.atan2(endY - startY, endX - startX) * 180 / Math.PI;
            
            // 创建线条元素
            const line = document.createElement('div');
            line.className = 'join-line';
            line.style.left = `${startX}px`;
            line.style.top = `${startY}px`;
            line.style.width = '0';
            line.style.transform = `rotate(${angle}deg)`;
            line.style.transition = `width ${duration / 1000}s ease`;
            
            animationContainer.appendChild(line);
            
            // 触发重排
            line.offsetHeight;
            
            // 开始动画
            line.style.width = `${length}px`;
            
            return line;
        }

        // 移除所有连接线
        function removeAllLines() {
            const lines = animationContainer.querySelectorAll('.join-line');
            lines.forEach(line => line.remove());
        }

        // 闪烁元素
        function blinkElement(element, times = 2, interval = 300) {
            let count = 0;
            const originalOpacity = element.style.opacity;
            
            function toggleOpacity() {
                if (count >= times * 2) {
                    element.style.opacity = originalOpacity;
                    return;
                }
                
                element.style.opacity = element.style.opacity === '0.5' ? '1' : '0.5';
                count++;
                
                setTimeout(toggleOpacity, interval);
            }
            
            toggleOpacity();
        }

        // 演示子查询更新过程
        function demoSubqueryUpdate() {
            resetDemo();
            
            // 禁用按钮防止重复点击
            btnSubquery.disabled = true;
            btnJoin.disabled = true;
            
            // 步骤1: 展示原始数据
            setTimeout(() => {
                updateInfoText('这是数据库中的原始数据。我们需要将学号为 <span class="sql-highlight">21021103</span> 的学生在 <span class="sql-highlight">C语言</span> 课程的成绩更新为 <span class="sql-highlight">90</span>。');
                
                // 步骤2: 执行子查询找出C语言课程的课程号
                setTimeout(() => {
                    highlightStep(1);
                    updateInfoText('首先执行子查询 <span class="sql-highlight">SELECT cno FROM course WHERE cname=\'C语言\'</span> 来获取C语言课程的课程号。');
                    
                    // 高亮课程表中的C语言行
                    const courseRow = courseTableBody.querySelectorAll('tr')[0]; // C语言是第一行
                    courseRow.classList.add('bg-purple-100', 'pulse');
                    
                    // 步骤3: 子查询结果作为主查询条件
                    setTimeout(() => {
                        highlightStep(2);
                        updateInfoText('子查询返回结果 <span class="sql-highlight">CS001</span>，现在使用这个结果作为主查询的条件。');
                        
                        // 移除课程行的动画
                        courseRow.classList.remove('pulse');
                        
                        // 高亮成绩表中匹配的记录
                        const scRows = scTableBody.querySelectorAll('tr');
                        let targetRow = null;
                        
                        for (let i = 0; i < scRows.length; i++) {
                            const snoCell = scRows[i].querySelector('td:first-child');
                            const cnoCell = scRows[i].querySelector('td:nth-child(2)');
                            
                            if (snoCell.textContent === '21021103' && cnoCell.textContent === 'CS001') {
                                targetRow = scRows[i];
                                break;
                            }
                        }
                        
                        if (targetRow) {
                            targetRow.classList.add('bg-yellow-100', 'pulse');
                        }
                        
                        // 步骤4: 执行更新操作
                        setTimeout(() => {
                            highlightStep(3);
                            updateInfoText('现在执行更新操作，将匹配的记录的成绩设置为90分。');
                            
                            // 闪烁要更新的单元格
                            if (targetRow) {
                                const gradeCell = targetRow.querySelector('td:last-child');
                                const oldGrade = gradeCell.textContent;
                                
                                // 创建过渡效果
                                gradeCell.classList.add('bg-warning');
                                
                                // 更新成绩
                                setTimeout(() => {
                                    gradeCell.textContent = '90';
                                    gradeCell.classList.remove('bg-warning');
                                    gradeCell.classList.add('bg-success/20');
                                }, 500);
                            }
                            
                            // 更新数据源中的成绩
                            const scoreIndex = scores.findIndex(s => s.sno === '21021103' && s.cno === 'CS001');
                            if (scoreIndex !== -1) {
                                scores[scoreIndex].grade = 90;
                            }
                            
                            // 步骤5: 展示更新结果
                            setTimeout(() => {
                                highlightStep(4);
                                updateInfoText('更新完成！学号为 <span class="sql-highlight">21021103</span> 的学生在C语言课程的成绩已成功更新为 <span class="sql-highlight">90</span> 分。');
                                
                                if (targetRow) {
                                    targetRow.classList.remove('pulse');
                                    setTimeout(() => {
                                        targetRow.classList.remove('bg-yellow-100', 'bg-success/20');
                                    }, 1000);
                                }
                                
                                // 重新启用按钮
                                btnSubquery.disabled = false;
                                btnJoin.disabled = false;
                            }, ANIMATION_DELAY);
                        }, ANIMATION_DELAY);
                    }, ANIMATION_DELAY);
                }, ANIMATION_DELAY);
            }, 500);
        }

        // 演示JOIN更新过程
        function demoJoinUpdate() {
            resetDemo();
            
            // 禁用按钮防止重复点击
            btnSubquery.disabled = true;
            btnJoin.disabled = true;
            
            // 步骤1: 展示原始数据
            setTimeout(() => {
                updateInfoText('这是数据库中的原始数据。我们需要使用JOIN方式将学号为 <span class="sql-highlight">21021103</span> 的学生在 <span class="sql-highlight">C语言</span> 课程的成绩更新为 <span class="sql-highlight">90</span>。');
                
                // 步骤2: 执行表连接操作
                setTimeout(() => {
                    highlightStep(1);
                    updateInfoText('首先执行表连接操作 <span class="sql-highlight">SC JOIN course ON SC.cno=course.cno</span>，将成绩表和课程表通过课程号连接起来。');
                    
                    // 高亮课程表中的C语言行
                    const courseRow = courseTableBody.querySelectorAll('tr')[0]; // C语言是第一行
                    courseRow.classList.add('bg-purple-100');
                    
                    // 高亮成绩表中C语言课程的记录
                    const scRows = scTableBody.querySelectorAll('tr');
                    let targetRow = null;
                    
                    for (let i = 0; i < scRows.length; i++) {
                        const cnoCell = scRows[i].querySelector('td:nth-child(2)');
                        
                        if (cnoCell.textContent === 'CS001') {
                            scRows[i].classList.add('bg-yellow-50');
                            
                            // 找到目标学生的记录
                            const snoCell = scRows[i].querySelector('td:first-child');
                            if (snoCell.textContent === '21021103') {
                                targetRow = scRows[i];
                            }
                        }
                    }
                    
                    // 创建连接线表示表连接
                    setTimeout(() => {
                        // 创建从课程表C语言行到成绩表C语言课程记录的连接线
                        const courseCnoCell = courseRow.querySelector('td:first-child');
                        
                        scRows.forEach(row => {
                            const cnoCell = row.querySelector('td:nth-child(2)');
                            if (cnoCell.textContent === 'CS001') {
                                createConnectionLine(courseCnoCell, cnoCell);
                            }
                        });
                        
                        // 步骤3: 应用WHERE条件
                        setTimeout(() => {
                            highlightStep(2);
                            updateInfoText('应用WHERE条件 <span class="sql-highlight">WHERE sno=\'21021103\' AND cname=\'C语言\'</span>，筛选出要更新的记录。');
                            
                            // 高亮学生表中的目标学生
                            const studentRow = studentTableBody.querySelectorAll('tr')[2]; // 王五是第三行
                            studentRow.classList.add('bg-blue-100');
                            
                            // 只有目标记录保持高亮，其他记录取消高亮
                            scRows.forEach(row => {
                                const snoCell = row.querySelector('td:first-child');
                                const cnoCell = row.querySelector('td:nth-child(2)');
                                
                                if (snoCell.textContent !== '21021103' || cnoCell.textContent !== 'CS001') {
                                    row.classList.remove('bg-yellow-50');
                                } else {
                                    row.classList.add('bg-yellow-100', 'pulse');
                                }
                            });
                            
                            // 步骤4: 执行更新操作
                            setTimeout(() => {
                                highlightStep(3);
                                updateInfoText('现在执行更新操作，将匹配的记录的成绩设置为90分。');
                                
                                // 闪烁要更新的单元格
                                if (targetRow) {
                                    const gradeCell = targetRow.querySelector('td:last-child');
                                    
                                    // 创建过渡效果
                                    gradeCell.classList.add('bg-warning');
                                    
                                    // 更新成绩
                                    setTimeout(() => {
                                        gradeCell.textContent = '90';
                                        gradeCell.classList.remove('bg-warning');
                                        gradeCell.classList.add('bg-success/20');
                                    }, 500);
                                }
                                
                                // 更新数据源中的成绩
                                const scoreIndex = scores.findIndex(s => s.sno === '21021103' && s.cno === 'CS001');
                                if (scoreIndex !== -1) {
                                    scores[scoreIndex].grade = 90;
                                }
                                
                                // 步骤5: 展示更新结果
                                setTimeout(() => {
                                    highlightStep(4);
                                    updateInfoText('更新完成！通过JOIN方式，学号为 <span class="sql-highlight">21021103</span> 的学生在C语言课程的成绩已成功更新为 <span class="sql-highlight">90</span> 分。');
                                    
                                    // 清理样式
                                    if (targetRow) {
                                        targetRow.classList.remove('pulse');
                                    }
                                    
                                    setTimeout(() => {
                                        courseRow.classList.remove('bg-purple-100');
                                        studentRow.classList.remove('bg-blue-100');
                                        if (targetRow) {
                                            targetRow.classList.remove('bg-yellow-100', 'bg-success/20');
                                        }
                                        removeAllLines();
                                    }, 1000);
                                    
                                    // 重新启用按钮
                                    btnSubquery.disabled = false;
                                    btnJoin.disabled = false;
                                }, ANIMATION_DELAY);
                            }, ANIMATION_DELAY);
                        }, ANIMATION_DELAY);
                    }, ANIMATION_DELAY);
                }, ANIMATION_DELAY);
            }, 500);
        }

        // 重置演示
        function resetDemo() {
            // 重置数据
            scores = JSON.parse(JSON.stringify(originalScores));
            
            // 重新渲染表格
            renderTables();
            
            // 重置步骤
            resetSteps();
            
            // 清除所有连接线
            removeAllLines();
        }

        // 事件监听器
        btnSubquery.addEventListener('click', demoSubqueryUpdate);
        btnJoin.addEventListener('click', demoJoinUpdate);
        btnReset.addEventListener('click', resetDemo);

        // 页面加载完成后初始化
        window.addEventListener('DOMContentLoaded', initializePage);
    </script>
</body>
</html>